<template>
  <div class="budget-project">
    <t-space class="left" direction="vertical">
      <!-- 引入方案按钮 -->
      <import-programme-btn
        v-if="props.orderId && props.companyId"
        :order-id="props.orderId"
        :company-id="props.companyId"
        @request-success="handleImportProgrammeRequestSuccess"
      />
      <!-- 下载按钮 -->
      <download-button
        :api="exportBudgetProject"
        :params="{ orderId: props.orderId }"
        content="导出预算"
        file-type="excel"
        file-name="预算文件"
      />
      <t-button block @click="handleOpenDialog('create', { isCategory: 1, parentId: 0 })"> 新建类目 </t-button>
      <t-tree
        :data="categoryTree"
        activable
        expand-on-click-node
        hover
        :keys="{ label: 'name', value: 'id' }"
        @click="handleClickCategoryTree"
      >
        <template #label="{ node }">
          {{ `${node.label}(${node.data.price})` }}
        </template>
        <template #operations="{ node }">
          <t-space>
            <t-icon name="add" @click="handleOpenDialog('create', { isCategory: 1, parentId: node.data.id })" />
            <t-icon
              name="edit"
              @click="handleOpenDialog('update', { id: node.data.id, isCategory: node.data.isCategory })"
            />
            <t-popconfirm
              content="确认要删除该项吗？"
              @confirm="handleDelete({ id: node.data.id, isCategory: node.data.isCategory })"
            >
              <t-icon name="delete" />
            </t-popconfirm>
          </t-space>
        </template>
      </t-tree>
    </t-space>
    <t-divider class="divider" layout="vertical" />
    <div v-show="selectedParentId" class="right">
      <!-- 自定义搜索 -->
      <custom-search ref="customSearchRef" v-slot="{ params }" @submit="handleInitTable">
        <t-col :span="4">
          <t-form-item label="施工阶段" name="constructionStage">
            <t-select
              v-model:value="params.constructionStage"
              :options="dictionaryStore.get('decoration_construction_order_stage')"
              clearable
              filterable
              placeholder=""
            />
          </t-form-item>
        </t-col>
        <t-col :span="4">
          <t-form-item label="项目名称" name="name">
            <t-input v-model:value="params.name" clearable placeholder="" />
          </t-form-item>
        </t-col>
      </custom-search>
      <!-- 自定义表格 -->
      <custom-table
        ref="customTableRef"
        row-key="id"
        :columns="columns"
        :api="budgetProjectCRUD.list"
        column-controller-key="budgetProjectList"
      >
        <template #topContent>
          <div style="margin-bottom: var(--td-comp-margin-xxl)">
            <t-button
              @click="
                handleOpenDialog('create', {
                  isCategory: 0,
                  parentId: selectedParentId,
                  materialList: [],
                  laborCostsList: [],
                })
              "
            >
              新建项目
            </t-button>
          </div>
        </template>
        <template #parentId="{ row }">
          {{ categoryList.find((item) => item.id === row.parentId)?.name }}
        </template>
        <template #constructionStage="{ row }">
          {{ dictionaryStore.analysis('decoration_construction_order_stage', row.constructionStage) }}
        </template>
        <template #unit="{ row }">
          {{ dictionaryStore.analysis('decoration_budget_unit', row.unit) }}
        </template>
        <template #profitMargin="{ row }">
          {{ `${((row.price / row.costPrice - 1) * 100).toFixed(2)}%` }}
        </template>
        <template #createTime="{ row }">
          {{ dayjs(row.createTime).format('YYYY-MM-DD HH:mm:ss') }}
        </template>
        <template #operation="{ row }">
          <t-space>
            <t-link
              v-permission="['decoration:material-library:query']"
              theme="primary"
              @click="handleOpenDialog('read', { id: row.id })"
            >
              详情
            </t-link>
            <t-link
              v-permission="['decoration:material-library:update']"
              theme="primary"
              @click="handleOpenDialog('update', { id: row.id })"
            >
              编辑
            </t-link>
            <t-popconfirm
              content="确认要删除该项吗？"
              @confirm="handleDelete({ id: row.id, isCategory: row.isCategory })"
            >
              <t-link v-permission="['decoration:material-library:delete']" theme="danger"> 删除 </t-link>
            </t-popconfirm>
          </t-space>
        </template>
      </custom-table>
    </div>
    <t-empty v-show="!selectedParentId" class="right" title="请先选择类目" style="margin-top: 200px" />
  </div>
  <!-- 自定义对话框 -->
  <custom-dialog
    ref="customDialogRef"
    v-slot="{ formData, readonly, mode }"
    :api-map="budgetProjectCRUD"
    header="*项目"
    width="80%"
    @request-success="handleDialogRequestSuccess"
  >
    <t-form-item
      v-if="formData.parentId !== 0"
      label="归属类目"
      name="parentId"
      :rules="[{ required: true, message: '请选择归属类目' }]"
    >
      <t-cascader
        v-model:value="formData.parentId"
        :options="categoryTree"
        :keys="{ label: 'name', value: 'id' }"
        placeholder="请选择归属类目"
        clearable
        filterable
        :readonly="readonly"
      />
    </t-form-item>
    <t-form-item
      v-if="formData.isCategory === 1"
      label="类目名称"
      name="name"
      :rules="[{ required: true, message: '请输入类目名称' }]"
    >
      <t-input v-model:value="formData.name" placeholder="请输入类目名称" clearable :readonly="readonly" />
    </t-form-item>
    <template v-else>
      <t-form-item
        v-if="mode === 'create'"
        label="快速导入"
        name="importId"
        :rules="[
          {
            validator: (value) => {
              if (!value) return true;
              const item = projectLibraryList.find((item) => item.id === value) || {};
              return !!item.constructionStage;
            },
            message: '该选项非项目，请重新选择',
          },
        ]"
      >
        <t-cascader
          v-model:value="formData.importId"
          :options="projectLibraryTree"
          :keys="{ label: 'name', value: 'id' }"
          placeholder="请选择导入项目名称"
          clearable
          filterable
          :readonly="readonly"
          @change="(value) => handleImport(value, formData)"
        />
      </t-form-item>
      <t-form-item label="施工阶段" name="constructionStage" :rules="[{ required: true, message: '请选择施工阶段' }]">
        <t-select
          v-model:value="formData.constructionStage"
          :options="dictionaryStore.get('decoration_construction_order_stage', 'number')"
          placeholder="请选择施工阶段"
          clearable
          filterable
          :readonly="readonly"
          @clear="formData.constructionStage = null"
        />
      </t-form-item>
      <t-form-item label="项目名称" name="name" :rules="[{ required: true, message: '请输入项目名称' }]">
        <t-input v-model:value="formData.name" placeholder="请输入项目名称" clearable :readonly="readonly" />
      </t-form-item>
      <t-form-item label="单位" name="unit" :rules="[{ required: true, message: '请选择单位' }]">
        <t-select
          v-model:value="formData.unit"
          :options="dictionaryStore.get('decoration_budget_unit', 'number')"
          placeholder="请选择单位"
          clearable
          filterable
          :readonly="readonly"
          @clear="formData.unit = null"
        />
      </t-form-item>
      <t-form-item label="数量" name="quantity" :rules="[{ required: true, message: '请输入数量' }]">
        <t-input-number
          v-model:value="formData.quantity"
          :decimal-places="0"
          min="0"
          :allow-input-over-limit="false"
          placeholder="请输入数量"
          :readonly="readonly"
          style="width: 100%"
        />
      </t-form-item>
      <t-form-item label="材料项" name="materialList" :rules="[{ required: true, message: '请选择材料项' }]">
        <div style="width: 100%">
          <t-table
            row-key="id"
            :data="formData.materialList"
            :columns="[
              { colKey: 'oldId', title: '材料项', width: 300 },
              { colKey: 'type', title: '材料类型' },
              { colKey: 'brand', title: '品牌名称' },
              { colKey: 'model', title: '型号' },
              { colKey: 'specification', title: '规格' },
              { colKey: 'unit', title: '单位' },
              { colKey: 'remark', title: '备注', width: 300 },
              { colKey: 'price', title: '售价(元)', fixed: 'right' },
              { colKey: 'finalPrice', title: '最终售价(元)', width: 120, fixed: 'right' },
              { colKey: 'costPrice', title: '成本价(元)', fixed: 'right' },
              { colKey: 'profitMargin', title: '利润率', fixed: 'right' },
              { colKey: 'discount', title: '折扣(%)', width: 150, fixed: 'right' },
              { colKey: 'quantity', title: '数量/比例', width: 160, fixed: 'right' },
              { colKey: 'operation', title: '操作', width: 70, fixed: 'right' },
            ]"
            bordered
            hover
            size="small"
            stripe
          >
            <template #oldId="{ row, rowIndex }">
              <t-form-item
                label="材料项"
                :name="`materialList[${rowIndex}].oldId`"
                :rules="[
                  { required: true, message: '请选择材料项' },
                  {
                    validator: (value) => {
                      const item = materialLibraryList.find((item) => item.id === value) || {};
                      return item.isCategory === 0;
                    },
                    message: '该选项非材料项，请重新选择',
                  },
                ]"
                label-width="0"
              >
                <t-cascader
                  v-model:value="row.oldId"
                  :options="materialLibraryTree"
                  :keys="{ label: 'name', value: 'id' }"
                  placeholder="请选择材料项"
                  clearable
                  filterable
                  :readonly="readonly"
                  @change="(value) => handleMaterialChange(value, row)"
                />
              </t-form-item>
            </template>
            <template #type="{ row }">
              {{ dictionaryStore.analysis('decoration_material_type', row.type) }}
            </template>
            <template #unit="{ row }">
              {{ dictionaryStore.analysis('decoration_budget_unit', row.unit) }}
            </template>
            <template #discount="{ row, rowIndex }">
              <t-form-item
                label="折扣"
                :name="`materialList[${rowIndex}].discount`"
                :rules="[{ required: true, message: '请输入折扣' }]"
                label-width="0"
              >
                <t-input-number
                  v-model:value="row.discount"
                  :decimal-places="0"
                  :min="0"
                  :max="100"
                  :allow-input-over-limit="false"
                  placeholder="请输入折扣"
                  :readonly="readonly"
                  style="width: 100%"
                />
              </t-form-item>
            </template>
            <template #finalPrice="{ row }">
              {{ (row.price - (row.price * row.discount) / 100).toFixed(2) }}
            </template>
            <template #profitMargin="{ row }">
              {{ `${(((row.price - (row.price * row.discount) / 100) / row.costPrice - 1) * 100).toFixed(2)}%` }}
            </template>
            <template #quantity="{ row, rowIndex }">
              <t-form-item
                label="数量/比例"
                :name="`materialList[${rowIndex}].quantity`"
                :rules="[{ required: true, message: '请输入数量/比例' }]"
                label-width="0"
              >
                <t-input-number
                  v-model:value="row.quantity"
                  :decimal-places="1"
                  min="0"
                  :allow-input-over-limit="false"
                  placeholder="请输入数量/比例"
                  :readonly="readonly"
                  style="width: 100%"
                />
              </t-form-item>
            </template>
            <template #remark="{ row, rowIndex }">
              <t-form-item label="备注" :name="`materialList[${rowIndex}].remark`" label-width="0">
                <t-textarea v-model:value="row.remark" placeholder="请输入备注" :readonly="readonly" />
              </t-form-item>
            </template>
            <template #operation="{ rowIndex }">
              <t-popconfirm content="确认要删除该项吗？" @confirm="formData.materialList.splice(rowIndex, 1)">
                <t-link v-if="!readonly" theme="danger"> 删除 </t-link>
              </t-popconfirm>
            </template>
          </t-table>
          <t-button v-if="!readonly" block @click="formData.materialList.push({})"> 添加材料项 </t-button>
        </div>
      </t-form-item>
      <t-form-item label="人工费用项" name="laborCostsList" :rules="[{ required: true, message: '请选择人工费用项' }]">
        <div style="width: 100%">
          <t-table
            row-key="id"
            :data="formData.laborCostsList"
            :columns="[
              { colKey: 'oldId', title: '人工费用项', width: 300 },
              { colKey: 'jobType', title: '工种类型' },
              { colKey: 'houseType', title: '房屋户型' },
              { colKey: 'unit', title: '单位' },
              { colKey: 'remark', title: '备注', width: 300 },
              { colKey: 'price', title: '售价(元)', fixed: 'right' },
              { colKey: 'finalPrice', title: '最终售价(元)', width: 120, fixed: 'right' },
              { colKey: 'costPrice', title: '成本价(元)', fixed: 'right' },
              { colKey: 'profitMargin', title: '利润率', fixed: 'right' },
              { colKey: 'discount', title: '折扣(%)', width: 150, fixed: 'right' },
              { colKey: 'quantity', title: '数量/比例', width: 160, fixed: 'right' },
              { colKey: 'operation', title: '操作', width: 70, fixed: 'right' },
            ]"
            bordered
            hover
            size="small"
            stripe
          >
            <template #oldId="{ row, rowIndex }">
              <t-form-item
                label="人工费用项"
                :name="`laborCostsList[${rowIndex}].oldId`"
                :rules="[
                  { required: true, message: '请选择人工费用项' },
                  {
                    validator: (value) => {
                      const item = laborCostsList.find((item) => item.id === value) || {};
                      return item.isCategory === 0;
                    },
                    message: '该选项非人工费用项，请重新选择',
                  },
                ]"
                label-width="0"
              >
                <t-cascader
                  v-model:value="row.oldId"
                  :options="laborCostsTree"
                  :keys="{ label: 'name', value: 'id' }"
                  placeholder="请选择人工费用项"
                  clearable
                  filterable
                  :readonly="readonly"
                  @change="(value) => handleLaborCostsChange(value, row)"
                />
              </t-form-item>
            </template>
            <template #jobType="{ row }">
              {{ dictionaryStore.analysis('decoration_job_type', row.jobType) }}
            </template>
            <template #houseType="{ row }">
              {{ dictionaryStore.analysis('decoration_order_house_type', row.houseType) }}
            </template>
            <template #unit="{ row }">
              {{ dictionaryStore.analysis('decoration_budget_unit', row.unit) }}
            </template>
            <template #discount="{ row, rowIndex }">
              <t-form-item
                label="折扣"
                :name="`laborCostsList[${rowIndex}].discount`"
                :rules="[{ required: true, message: '请输入折扣' }]"
                label-width="0"
              >
                <t-input-number
                  v-model:value="row.discount"
                  :decimal-places="0"
                  :min="0"
                  :max="100"
                  :allow-input-over-limit="false"
                  placeholder="请输入折扣"
                  :readonly="readonly"
                  style="width: 100%"
                />
              </t-form-item>
            </template>
            <template #finalPrice="{ row }">
              {{ (row.price - (row.price * row.discount) / 100).toFixed(2) }}
            </template>
            <template #profitMargin="{ row }">
              {{ `${(((row.price - (row.price * row.discount) / 100) / row.costPrice - 1) * 100).toFixed(2)}%` }}
            </template>
            <template #quantity="{ row, rowIndex }">
              <t-form-item
                label="数量/比例"
                :name="`laborCostsList[${rowIndex}].quantity`"
                :rules="[{ required: true, message: '请输入数量/比例' }]"
                label-width="0"
              >
                <t-input-number
                  v-model:value="row.quantity"
                  :decimal-places="1"
                  min="0"
                  :allow-input-over-limit="false"
                  placeholder="请输入数量/比例"
                  :readonly="readonly"
                  style="width: 100%"
                />
              </t-form-item>
            </template>
            <template #remark="{ row, rowIndex }">
              <t-form-item label="备注" :name="`laborCostsList[${rowIndex}].remark`" label-width="0">
                <t-textarea v-model:value="row.remark" placeholder="请输入备注" :readonly="readonly" />
              </t-form-item>
            </template>
            <template #operation="{ rowIndex }">
              <t-popconfirm content="确认要删除该项吗？" @confirm="formData.laborCostsList.splice(rowIndex, 1)">
                <t-link v-if="!readonly" theme="danger"> 删除 </t-link>
              </t-popconfirm>
            </template>
          </t-table>
          <t-button v-if="!readonly" block @click="formData.laborCostsList.push({})"> 添加人工费用项 </t-button>
        </div>
      </t-form-item>
      <t-form-item label="备注" name="remark">
        <t-textarea v-model:value="formData.remark" placeholder="请输入备注" :readonly="readonly" />
      </t-form-item>
    </template>
    <t-form-item label="排序" name="sort">
      <t-input-number
        v-model:value="formData.sort"
        :decimal-places="0"
        min="0"
        :allow-input-over-limit="false"
        placeholder="请输入排序"
        :readonly="readonly"
        style="width: 100%"
      />
    </t-form-item>
  </custom-dialog>
</template>

<script setup lang="ts">
import dayjs from 'dayjs';
import { CascaderValue, MessagePlugin, TableCol, TreeNodeModel } from 'tdesign-vue-next';
import { ref, useTemplateRef } from 'vue';

import { budgetProjectCRUD, exportBudgetProject } from '@/api/budget/budget-components';
import { laborCostsCRUD } from '@/api/budget/labor-costs';
import { materialLibraryCRUD } from '@/api/budget/material-library';
import { projectLibraryCRUD } from '@/api/budget/project-library';
import CustomDialog from '@/components/custom/dialog/index.vue';
import CustomSearch from '@/components/custom/search/index.vue';
import CustomTable from '@/components/custom/table/index.vue';
import DownloadButton from '@/components/download-button/index.vue';
import { useDictionaryStore } from '@/store';
import listToTree from '@/utils/listToTree';

import ImportProgrammeBtn from './ImportProgrammeBtn.vue';

// 字典仓库
const dictionaryStore = useDictionaryStore();
// props
const props = defineProps({
  // 方案id
  programmeId: {
    type: Number,
  },
  // 订单id
  orderId: {
    type: Number,
  },
  // 公司id
  companyId: {
    type: Number,
    required: true,
  },
});
// 选中的父级id
const selectedParentId = ref();
// 类目列表
const categoryList = ref([]);
// 类目树
const categoryTree = ref([]);
// 处理获取类目
const handleGetCategory = () => {
  const params = {
    programmeId: props.programmeId,
    orderId: props.orderId,
    isCategory: 1,
  };
  budgetProjectCRUD.list(params).then((data) => {
    categoryList.value = data;
    categoryTree.value = listToTree(data);
  });
};
handleGetCategory();
// 项目库列表
const projectLibraryList = ref([]);
// 项目库树
const projectLibraryTree = ref([]);
// 处理获取项目库
const handleGetProjectLibrary = () => {
  const params = {
    companyId: props.companyId,
  };
  projectLibraryCRUD.list(params).then((data) => {
    projectLibraryList.value = data;
    const tree = listToTree(data);
    projectLibraryTree.value = dictionaryStore.get('decoration_construction_order_stage', 'number').map((item) => {
      return {
        id: item.label,
        name: item.label,
        children: tree.filter((p: any) => p.constructionStage === item.value),
      };
    });
  });
};
// 材料库列表
const materialLibraryList = ref([]);
// 材料库树
const materialLibraryTree = ref([]);
// 处理获取材料库树
const handleGetMaterialLibrary = () => {
  const params = {
    companyId: props.companyId,
  };
  materialLibraryCRUD.list(params).then((data) => {
    materialLibraryList.value = data;
    const tree = listToTree(data);
    materialLibraryTree.value = dictionaryStore.get('decoration_material_type', 'number').map((item) => {
      return { id: item.label, name: item.label, children: tree.filter((t) => t.type === item.value) };
    });
  });
};
// 人工费用列表
const laborCostsList = ref([]);
// 人工费用树
const laborCostsTree = ref([]);
// 处理获取人工费用树
const handleGetLaborCosts = () => {
  const params = {
    companyId: props.companyId,
  };
  laborCostsCRUD.list(params).then((data) => {
    laborCostsList.value = data;
    const tree = listToTree(data);
    laborCostsTree.value = dictionaryStore.get('decoration_job_type', 'number').map((item) => {
      return { id: item.label, name: item.label, children: tree.filter((t) => t.jobType === item.value) };
    });
  });
};
// 自定义搜索ref
const customSearchRef = useTemplateRef('customSearchRef');
// 自定义表格ref
const customTableRef = useTemplateRef('customTableRef');
// columns
const columns: TableCol[] = [
  { colKey: 'parentId', title: '归属类目' },
  { colKey: 'constructionStage', title: '施工阶段' },
  { colKey: 'name', title: '项目名称' },
  { colKey: 'unit', title: '单位' },
  { colKey: 'quantity', title: '数量' },
  { colKey: 'price', title: '售价(元)' },
  { colKey: 'costPrice', title: '成本价(元)' },
  { colKey: 'profitMargin', title: '利润率' },
  { colKey: 'remark', title: '备注' },
  { colKey: 'createTime', title: '创建时间', width: 180 },
  { colKey: 'operation', title: '操作', width: 150, fixed: 'right' },
];
// 处理初始化表格
const handleInitTable = () => {
  const params = {
    ...customSearchRef.value.params,
    parentId: selectedParentId.value,
  };
  customTableRef.value.initTable(params);
};
// 处理刷新表格
const handleRefreshTable = () => {
  customTableRef.value.refreshTable();
};
// 自定义对话框ref
const customDialogRef = useTemplateRef('customDialogRef');
// 处理打开对话框
const handleOpenDialog = (mode: 'create' | 'read' | 'update', params: Record<string, any>) => {
  if (params.isCategory !== 1) {
    handleGetProjectLibrary();
    handleGetMaterialLibrary();
    handleGetLaborCosts();
  }
  customDialogRef.value.open(mode, { ...params, programmeId: props.programmeId, orderId: props.orderId });
};
// 处理对话框请求成功
const handleDialogRequestSuccess = (result: Record<string, any>) => {
  handleGetCategory();
  if (result.params.isCategory !== 1) {
    if (result.mode === 'create') handleInitTable();
    if (result.mode === 'update') handleRefreshTable();
  }
};
// 处理删除
const handleDelete = (params: Record<string, any>) => {
  budgetProjectCRUD
    .delete(params)
    .then(() => {
      MessagePlugin.success('删除成功');
      handleGetCategory();
      if (params.isCategory !== 1) {
        handleRefreshTable();
      }
    })
    .catch(({ message }) => {
      MessagePlugin.error(message);
    });
};
// 处理点击类目树
const handleClickCategoryTree = ({ node }: { node: TreeNodeModel }) => {
  if (node.data.parentId) {
    selectedParentId.value = node.value;
    handleInitTable();
  }
};
// 处理导入
const handleImport = (value: CascaderValue, formData: Record<string, any>) => {
  if (!value) return;
  // 判断是否为项目
  const project = projectLibraryList.value.find((item) => item.id === value) || {};
  if (project.isCategory !== 0) return;
  // 回填
  formData.constructionStage = project.constructionStage;
  formData.name = project.name;
  formData.unit = project.unit;
  formData.materialList = project.materialIds.map((item: { id: number; quantity: number }) => {
    const material = materialLibraryList.value.find((m) => m.id === item.id) || {};
    return { ...material, oldId: material.id, id: null, quantity: item.quantity, discount: 0 };
  });
  formData.laborCostsList = project.laborCostsIds.map((item: { id: number; quantity: number }) => {
    const laborCosts = laborCostsList.value.find((l) => l.id === item.id) || {};
    return { ...laborCosts, oldId: laborCosts.id, id: null, quantity: item.quantity, discount: 0 };
  });
  formData.remark = project.remark;
};
// 处理材料改变
const handleMaterialChange = (value: CascaderValue, row: Record<string, any>) => {
  const item = materialLibraryList.value.find((item) => item.id === value) || {};
  if (item.isCategory !== 0) return;
  const oldId = row.id;
  Object.keys(item).forEach((key) => {
    row[key] = item[key];
  });
  if (oldId) {
    row.id = oldId;
  } else {
    row.id = null;
  }
  row.discount = 0;
};
// 处理人工费用改变
const handleLaborCostsChange = (value: CascaderValue, row: Record<string, any>) => {
  const item = laborCostsList.value.find((item) => item.id === value) || {};
  if (item.isCategory !== 0) return;
  const oldId = row.id;
  Object.keys(item).forEach((key) => {
    row[key] = item[key];
  });
  if (oldId) {
    row.id = oldId;
  } else {
    row.id = null;
  }
  row.discount = 0;
};
// 处理引入方案请求成功
const handleImportProgrammeRequestSuccess = () => {
  handleGetCategory();
  selectedParentId.value = null;
};
</script>

<style lang="less" scoped>
.budget-project {
  display: flex;
  justify-content: flex-start;
  align-items: flex-start;

  .left {
    width: 300px;
  }

  .divider {
    height: 500px;
  }

  .right {
    width: 100%;
  }
}
</style>
